<template>
    <div>
      <div id="map" class="mapC"></div>
      <div class="eventC" style="width: 50vw;">
        <el-select v-model="value" placeholder="请选择" @change="changeSelect">
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
          </el-option>
        </el-select>
        <el-button type="primary" @click="delDraw">清除画笔</el-button>
      </div>
    </div>
</template>

<script>
import 'ol/ol.css'
import Draw from 'ol/interaction/Draw'
import Map from 'ol/Map'
import Overlay from 'ol/Overlay'
import View from 'ol/View'
import {ScaleLine} from 'ol/control'
import {Circle as CircleStyle, Fill, Stroke, Style} from 'ol/style'
import {LineString, Polygon} from 'ol/geom'
import {OSM, Vector as VectorSource} from 'ol/source'
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer'
import {getArea, getLength} from 'ol/sphere'
import {unByKey} from 'ol/Observable'
export default {
  name: 'index',
  data () {
    return {
      value: 'Length (LineString)',
      options: [
        {
          label: 'Length (LineString)',
          value: 'Length'
        },
        {
          label: 'Area (Polygon)',
          value: 'area'
        }
      ],
      raster: null,
      vector: null,
      draw: null,
      typeSelect: null,
      sketch: null,
      sketch1: 1,
      helpTooltipElement: null,
      helpTooltip: null,
      measureTooltipElement: null,
      measureTooltip: null,
      continuePolygonMsg: 'Click to continue drawing the polygon',
      continueLineMsg: 'Click to continue drawing the line',
      source: null
    }
  },
  mounted () {
    this.initMap()
    this.addInteraction()
  },
  methods: {
    initMap () {
      this.raster = new TileLayer({
        source: new OSM()
      })

      this.source = new VectorSource()

      this.vector = new VectorLayer({
        source: this.source,
        style: new Style({
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          }),
          stroke: new Stroke({
            color: '#ffcc33',
            width: 2
          }),
          image: new CircleStyle({
            radius: 7,
            fill: new Fill({
              color: '#ffcc33'
            })
          })
        })
      })
      this.map = new Map({
        layers: [this.raster, this.vector],
        target: 'map',
        view: new View({
          center: [-11000000, 4600000],
          zoom: 15
        })
      })
      this.map.addControl(new ScaleLine({bar: true, text: true, minWidth: 125}))
      // this.map.addControl(new ScaleLine({units: 'metric'}))
      this.map.on('pointermove', this.pointerMoveHandler)

      this.map.getViewport().addEventListener('mouseout', () => {
        this.helpTooltipElement.classList.add('hidden')
      })
    },
    changeSelect (val) {
      this.map.removeInteraction(this.draw)
      this.addInteraction()
      this.sketch1 = 1
    },
    delDraw (val) {
      this.map.removeInteraction(this.draw)
      this.sketch1 = null
      // this.addInteraction()
    },
    pointerMoveHandler (evt) {
      if (evt.dragging) {
        return
      }
      let helpMsg = ''
      /** @type {string} */
      if (this.sketch1) {
        helpMsg = 'Click to start drawing'
      } else {
        helpMsg = ''
      }

      if (this.sketch) {
        const geom = this.sketch.getGeometry()
        if (geom instanceof Polygon) {
          helpMsg = this.continuePolygonMsg
        } else if (geom instanceof LineString) {
          helpMsg = this.continueLineMsg
        }
      }

      this.helpTooltipElement.innerHTML = helpMsg
      this.helpTooltip.setPosition(evt.coordinate)

      this.helpTooltipElement.classList.remove('hidden')
    },
    formatLength (line) {
      const length = getLength(line)
      let output
      if (length > 100) {
        output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'
      } else {
        output = Math.round(length * 100) / 100 + ' ' + 'm'
      }
      return output
    },
    formatArea (polygon) {
      const area = getArea(polygon)
      let output
      if (area > 10000) {
        output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>'
      } else {
        output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'
      }
      return output
    },
    addInteraction () {
      const type = this.value === 'area' ? 'Polygon' : 'LineString'
      this.draw = new Draw({
        source: this.source,
        type: type,
        style: new Style({
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          }),
          stroke: new Stroke({
            color: 'rgba(0, 0, 0, 0.5)',
            lineDash: [10, 10],
            width: 2
          }),
          image: new CircleStyle({
            radius: 5,
            stroke: new Stroke({
              color: 'rgba(0, 0, 0, 0.7)'
            }),
            fill: new Fill({
              color: 'rgba(255, 255, 255, 0.2)'
            })
          })
        })
      })
      this.map.addInteraction(this.draw)

      this.createMeasureTooltip()
      this.createHelpTooltip()

      let listener
      this.draw.on('drawstart', (evt) => {
        // set sketch
        this.sketch = evt.feature

        /** @type {import("../src/ol/coordinate.js").Coordinate|undefined} */
        let tooltipCoord = evt.coordinate

        listener = this.sketch.getGeometry().on('change', (evt) => {
          // let that = this
          const geom = evt.target
          let output
          if (geom instanceof Polygon) {
            output = this.formatArea(geom)
            tooltipCoord = geom.getInteriorPoint().getCoordinates()
          } else if (geom instanceof LineString) {
            output = this.formatLength(geom)
            tooltipCoord = geom.getLastCoordinate()
          }
          this.measureTooltipElement.innerHTML = output
          this.measureTooltip.setPosition(tooltipCoord)
        })
      })

      this.draw.on('drawend', () => {
        this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'
        this.measureTooltip.setOffset([0, -7])
        // unset sketch
        this.sketch = null
        // unset tooltip so that a new one can be created
        this.measureTooltipElement = null
        this.createMeasureTooltip()
        unByKey(listener)
        this.delDraw()
      })
    },
    createHelpTooltip () {
      if (this.helpTooltipElement) {
        this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement)
      }
      this.helpTooltipElement = document.createElement('div')
      this.helpTooltipElement.className = 'ol-tooltip hidden'
      this.helpTooltip = new Overlay({
        element: this.helpTooltipElement,
        offset: [15, 0],
        positioning: 'center-left'
      })
      this.map.addOverlay(this.helpTooltip)
    },
    createMeasureTooltip () {
      if (this.measureTooltipElement) {
        this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement)
      }
      this.measureTooltipElement = document.createElement('div')
      this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'
      this.measureTooltip = new Overlay({
        element: this.measureTooltipElement,
        offset: [0, -15],
        positioning: 'bottom-center',
        stopEvent: false,
        insertFirst: false
      })
      this.map.addOverlay(this.measureTooltip)
    }
  }
}
</script>

<style scoped>
  .ol-tooltip {
    position: relative;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 4px;
    color: white;
    padding: 4px 8px;
    opacity: 0.7;
    white-space: nowrap;
    font-size: 12px;
    cursor: default;
    user-select: none;
  }
  .ol-tooltip-measure {
    opacity: 1;
    font-weight: bold;
  }
  .ol-tooltip-static {
    background-color: #ffcc33;
    color: black;
    border: 1px solid white;
  }
  .ol-tooltip-measure:before,
  .ol-tooltip-static:before {
    border-top: 6px solid rgba(0, 0, 0, 0.5);
    border-right: 6px solid transparent;
    border-left: 6px solid transparent;
    content: "";
    position: absolute;
    bottom: -6px;
    margin-left: -7px;
    left: 50%;
  }
  .ol-tooltip-static:before {
    border-top-color: #ffcc33;
  }

</style>
